package com.huanghuang.shuadan.common.utils.jwt;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.huanghuang.shuadan.common.utils.DateTool.DateTool;
import com.huanghuang.shuadan.service.entity.res.UserResDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
@Component
@Slf4j
public class JWTTooL {
    private final String secret = "shuadn";//token 密钥
    private final Algorithm algorithm = Algorithm.HMAC256("secret");

    //头部信息
    private Map<String, Object> map = new HashMap<String, Object>(){{
        put("alg", "HS256");
        put("typ", "JWT");
    }};

    public String createToken() {

        try {

            Date nowDate = new Date();
            Date expireDate = DateTool.getAfterDate(nowDate,0,0,10,0,0,0);//2小过期

            String token = JWT.create()
                    /*设置头部信息 Header*/
                    .withHeader(map)
                    /*设置 载荷 Payload*/
                    .withIssuer("SERVICE")//签名是有谁生成 例如 服务器
                    .withSubject("jwt")//签名的主题
                    //.withNotBefore(new Date())//定义在什么时间之前，该jwt都是不可用的.
                    .withAudience("APP")//签名的观众 也可以理解谁接受签名的
                    .withIssuedAt(nowDate) //生成签名的时间
                    .withExpiresAt(expireDate)//签名过期的时间
                    /*签名 Signature */
                    .sign(algorithm);
            return token;
        } catch (JWTCreationException exception){
            exception.printStackTrace();
        }
        return null;
    }
    public String createTokenWithClaim(UserResDTO userResDTO) {

        try {
            Date nowDate = new Date();
            Date expireDate = DateTool.getAfterDate(nowDate,0,0,0,2,0,0);//2小过期
            log.info("JWT加密对象:{}", userResDTO);
            Algorithm algorithm = Algorithm.HMAC256("secret");
            String token = JWT.create()
                    .withHeader(map)
                    /*设置 载荷 Payload*/
                    .withClaim("user", JSON.toJSONString(userResDTO))
                    .withIssuer("SERVICE")//签名是有谁生成 例如 服务器
                    .withSubject("jwt")//签名的主题
                    .withAudience("APP")//签名的观众 也可以理解谁接受签名的
                    .withIssuedAt(nowDate) //生成签名的时间
                    .withExpiresAt(expireDate)//签名过期的时间
                    /*签名 Signature */
                    .sign(algorithm);
            log.info("JWT生成token:{}", token);
            return token;
        } catch (JWTCreationException exception){
            exception.printStackTrace();
        }
        return null;
    }
    /**
     * 解密
     * @param token
     * @return
     */
    public static void verifyToken(String token) {
        try {
            Algorithm algorithm = Algorithm.HMAC256("secret");
            JWTVerifier verifier = JWT.require(algorithm)
                    .withIssuer("SERVICE")
                    .build(); //Reusable verifier instance

            DecodedJWT jwt = verifier.verify(token);
            String subject = jwt.getSubject();
            List<String> audience = jwt.getAudience();
            Map<String, Claim> claims = jwt.getClaims();

            Claim claim = claims.get("user");
            UserResDTO userResDTO = JSON.parseObject(claim.asString(),UserResDTO.class);
            log.info("JWT解码对象:{}", userResDTO);
            // System.out.println("2"+subject);
            // System.out.println("3"+audience.get(0));
        } catch (JWTVerificationException exception){
            exception.printStackTrace();
        }
    }

    public static void main(String[] args) {
        JWTTooL demo = new JWTTooL();
        //String createToken = demo.createToken();
        UserResDTO user = new UserResDTO();
        String createTokenWithClaim = demo.createTokenWithClaim(user);
        demo.verifyToken(createTokenWithClaim);
    }
}
